package com.grupoconstruobras.sijt.security.auth.listener;

import java.io.Serializable;
import java.util.List;

import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.el.ELContext;
import javax.el.ExpressionFactory;


public class SecurityListener implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	
	public SecurityListener(){
		
	}
	
	
	/**
	 * Método principal para busqueda de in componente dado su id, toma el facesContext y extrae la raiz del árbol
	 * @param facesContext
	 * @param id
	 * @return UIComponent
	 */
	public UIComponent findComponent(FacesContext facesContext, String id) {

		UIComponent result = null;
		UIComponent root = facesContext.getViewRoot();
		if (root != null) {
			result = findComponent(root, id);
		}
		return result;

	}

	/**
	 * Método recursivo para buscar un componente dentro del árbol de componentes dado su id
	 * @param root
	 * @param id
	 * @return UIComponent
	 */
	private UIComponent findComponent(UIComponent root, String id) {

		UIComponent result = null;
		if (root.getId().equals(id))
			return root;

		for (UIComponent child : root.getChildren()) {
			if (child.getId().equals(id)) {
				result = child;
				break;
			}
			result = findComponent(child, id);
			if (result != null)
				break;
		}
		return result;
	}
	
	private ValueExpression getValueExpression(FacesContext facesContext, String name) {
	    Application app = facesContext.getApplication();
	    ExpressionFactory elFactory = app.getExpressionFactory();
	    ELContext elContext = facesContext.getELContext();
	    return elFactory.createValueExpression(elContext, name, Object.class);
	}
	
	/**
	 * Método que toma los componentes enviados en la lista y por medio de su  id los busca y marca como readOnly = "false"
	 * y disabled = "false"
	 * @param facesContext
	 */
	public void aplicarConfiguracionSeguridadSoloLectura(FacesContext facesContext, List<String> componentes){
		
				
		if(componentes != null){
			for(String idComp : componentes){
				UIComponent component = null;
				component = findComponent(facesContext, idComp);
				
		        if(component != null){
		        	
		        	component.setValueExpression("readOnly", getValueExpression(facesContext, "#{true}"));
			        component.setValueExpression("disabled", getValueExpression(facesContext, "#{true}"));
		        	
		        }
		        
			}
			
		}
		
	}

	/**
	 * Método que toma los componentes enviados en la lista y por medio de su  id los busca y marca como rendered = "false"
	 * @param facesContext
	 * @param componentes
	 */
	public void aplicarConfiguracionSeguridaOcultarComponentes(
			FacesContext facesContext, List<String> componentes, boolean esMenu) {

		if(componentes != null){
			for(String idComp : componentes){
				UIComponent component = null;
				component = findComponent(facesContext, idComp);

				if(esMenu){
					if(component != null){
						
						component.setValueExpression("rendered", getValueExpression(facesContext, "#{true}"));
					}
				}else{
					if(component != null){
						
						component.setValueExpression("rendered", getValueExpression(facesContext, "#{false}"));
					}
				}


			}

		}

	}

	public void filtrarOpcionesNoConfiguradas(
			FacesContext facesContext, UIComponent root,List<String> componentes){
		
		
		if (root != null) {
			for (UIComponent child : root.getChildren()) {
			
								
				if (!componentes.contains(child.getId())) {
					child.setValueExpression("rendered", getValueExpression(facesContext, "#{false}"));
				}
				
				if(child.getChildren() != null){
					filtrarOpcionesNoConfiguradas(facesContext,child,componentes);
				}else{
					break;
				}
				
			}
		}
	}
	
	/**
	 * toma la confoguracion para las vistas por rol y solicita la renderizacion de los item de menu
	 * @param currentInstance
	 * @param componentes
	 */
	public void aplicarSeguridadMenu(FacesContext currentInstance,
			List<String> componentes) {
		
		
		aplicarConfiguracionSeguridaOcultarComponentes(currentInstance,componentes,true);

		filtrarOpcionesNoConfiguradas(currentInstance,currentInstance.getViewRoot(),componentes);
		
	}

}
